home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / include / asm / mach-default / mach_time.h < prev    next >
C/C++ Source or Header  |  2005-10-13  |  4KB  |  123 lines

  1. /*
  2.  *  include/asm-i386/mach-default/mach_time.h
  3.  *
  4.  *  Machine specific set RTC function for generic.
  5.  *  Split out from time.c by Osamu Tomita <tomita@cinet.co.jp>
  6.  */
  7. #ifndef _MACH_TIME_H
  8. #define _MACH_TIME_H
  9.  
  10. #include <linux/mc146818rtc.h>
  11.  
  12. /* for check timing call set_rtc_mmss() 500ms     */
  13. /* used in arch/i386/time.c::do_timer_interrupt() */
  14. #define USEC_AFTER    500000
  15. #define USEC_BEFORE    500000
  16.  
  17. /*
  18.  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
  19.  * called 500 ms after the second nowtime has started, because when
  20.  * nowtime is written into the registers of the CMOS clock, it will
  21.  * jump to the next second precisely 500 ms later. Check the Motorola
  22.  * MC146818A or Dallas DS12887 data sheet for details.
  23.  *
  24.  * BUG: This routine does not handle hour overflow properly; it just
  25.  *      sets the minutes. Usually you'll only notice that after reboot!
  26.  */
  27. static inline int mach_set_rtc_mmss(unsigned long nowtime)
  28. {
  29.     int retval = 0;
  30.     int real_seconds, real_minutes, cmos_minutes;
  31.     unsigned char save_control, save_freq_select;
  32.  
  33.     save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
  34.     CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
  35.  
  36.     save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
  37.     CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
  38.  
  39.     cmos_minutes = CMOS_READ(RTC_MINUTES);
  40.     if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  41.         BCD_TO_BIN(cmos_minutes);
  42.  
  43.     /*
  44.      * since we're only adjusting minutes and seconds,
  45.      * don't interfere with hour overflow. This avoids
  46.      * messing with unknown time zones but requires your
  47.      * RTC not to be off by more than 15 minutes
  48.      */
  49.     real_seconds = nowtime % 60;
  50.     real_minutes = nowtime / 60;
  51.     if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
  52.         real_minutes += 30;        /* correct for half hour time zone */
  53.     real_minutes %= 60;
  54.  
  55.     if (abs(real_minutes - cmos_minutes) < 30) {
  56.         if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  57.             BIN_TO_BCD(real_seconds);
  58.             BIN_TO_BCD(real_minutes);
  59.         }
  60.         CMOS_WRITE(real_seconds,RTC_SECONDS);
  61.         CMOS_WRITE(real_minutes,RTC_MINUTES);
  62.     } else {
  63.         printk(KERN_WARNING
  64.                "set_rtc_mmss: can't update from %d to %d\n",
  65.                cmos_minutes, real_minutes);
  66.         retval = -1;
  67.     }
  68.  
  69.     /* The following flags have to be released exactly in this order,
  70.      * otherwise the DS12887 (popular MC146818A clone with integrated
  71.      * battery and quartz) will not reset the oscillator and will not
  72.      * update precisely 500 ms later. You won't find this mentioned in
  73.      * the Dallas Semiconductor data sheets, but who believes data
  74.      * sheets anyway ...                           -- Markus Kuhn
  75.      */
  76.     CMOS_WRITE(save_control, RTC_CONTROL);
  77.     CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
  78.  
  79.     return retval;
  80. }
  81.  
  82. static inline unsigned long mach_get_cmos_time(void)
  83. {
  84.     unsigned int year, mon, day, hour, min, sec;
  85.     int i;
  86.  
  87.     /* The Linux interpretation of the CMOS clock register contents:
  88.      * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
  89.      * RTC registers show the second which has precisely just started.
  90.      * Let's hope other operating systems interpret the RTC the same way.
  91.      */
  92.     /* read RTC exactly on falling edge of update flag */
  93.     for (i = 0 ; i < 1000000 ; i++)    /* may take up to 1 second... */
  94.         if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
  95.             break;
  96.     for (i = 0 ; i < 1000000 ; i++)    /* must try at least 2.228 ms */
  97.         if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
  98.             break;
  99.     do { /* Isn't this overkill ? UIP above should guarantee consistency */
  100.         sec = CMOS_READ(RTC_SECONDS);
  101.         min = CMOS_READ(RTC_MINUTES);
  102.         hour = CMOS_READ(RTC_HOURS);
  103.         day = CMOS_READ(RTC_DAY_OF_MONTH);
  104.         mon = CMOS_READ(RTC_MONTH);
  105.         year = CMOS_READ(RTC_YEAR);
  106.     } while (sec != CMOS_READ(RTC_SECONDS));
  107.     if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  108.       {
  109.         BCD_TO_BIN(sec);
  110.         BCD_TO_BIN(min);
  111.         BCD_TO_BIN(hour);
  112.         BCD_TO_BIN(day);
  113.         BCD_TO_BIN(mon);
  114.         BCD_TO_BIN(year);
  115.       }
  116.     if ((year += 1900) < 1970)
  117.         year += 100;
  118.  
  119.     return mktime(year, mon, day, hour, min, sec);
  120. }
  121.  
  122. #endif /* !_MACH_TIME_H */
  123.